import base64
from datetime import datetime
from io import BytesIO

from flask import request, send_file
from qrcode.constants import ERROR_CORRECT_L
from qrcode.main import QRCode

from flaskapp.entity.Book import Book
from flaskapp.entity.Record import Record
from flaskapp.util import GPT
from flaskapp.util.Redprint import Redprint
from flaskapp.util.Result import Result

api = Redprint('books')


@api.route('/getBookByName', methods=['POST'])
def get_book():
    bookname = request.json.get('name')
    books = Book.query.filter_by(bookname=bookname).all()
    book_list = []
    if not books:
        return Result.error(404, 'book not found'), 404
    else:
        for book in books:
            book_list.append(book.to_dict())
        return Result.success(book_list)


# 根据bookid获取书籍
@api.route('/getBookById/<bookid>', methods=['GET'])
def get_book_by_id(bookid):
    book = Book.query.filter_by(bookid=bookid).first()
    if not book:
        return Result.error(404, 'book not found')
    else:
        return Result.success(book.to_dict())


@api.route('/allBooks', methods=['GET'])
def get_all_books():
    books = Book.query.all()
    book_list = []
    for book in books:
        book_list.append(book.to_dict())
    return Result.success(book_list)


# 搜索图书
@api.route('/searchBook', methods=['POST'])
def search_book():
    keyword = request.json.get('keyword')
    if not keyword:
        return Result.error(404, 'no params')
    else:
        books = Book.query.filter(Book.bookname.like('%' + keyword + '%')).all()
        cover_dict = {}
        if not books:
            return Result.error(404, 'no such book')
        for book in books:
            coverURL = "http://127.0.0.1:5000/" + book.coverpath
            cover_dict[book.bookname] = {
                "coverURL": coverURL,
                'bookid': book.bookid
            }
        print(cover_dict)
        return Result.success(cover_dict)


# 获取所有图书的cover
@api.route('/allBookCover', methods=['GET'])
def get_all_book_cover():
    books = Book.query.all()
    cover_dict = {}
    for book in books:
        coverURL = "http://127.0.0.1:5000/"+book.coverpath
        cover_dict[book.bookname] = {
            "coverURL": coverURL,
            'bookid': book.bookid
        }
    return Result.success(cover_dict)


@api.route('/getBookCoverByCategory', methods=['POST'])
def get_book_cover_by_category():
    category = request.json.get('category')
    books = Book.query.filter_by(category=category).all()
    cover_dict = {}
    if not books:
        return Result.error(404, 'no such category')
    else:
        for book in books:
            coverURL = "http://127.0.0.1:5000/"+book.coverpath
            cover_dict[book.bookname] = {
                "coverURL": coverURL,
                'bookid': book.bookid
            }
        return Result.success(cover_dict)


# 获取所有类别
@api.route('/getAllCategories', methods=['GET'])
def getAllCategories():
    categories = Book.query.with_entities(Book.category).distinct().all()
    categories_list = [category[0] for category in categories]
    return Result.success(categories_list)


# 根据类别获取相应书籍
@api.route('/getBooksByCategory', methods=['POST'])
def get_books_by_category():
    category = request.json.get('category')
    books = Book.query.filter_by(category=category).all()
    if not books:
        return Result.error(404, 'book not found'), 404
    else:
        book_list = []
        for book in books:
            book_list.append(book.to_dict())
        return Result.success(book_list)


# 根据类别和书名返回书籍
@api.route('/getBooksByNameAndCategory', methods=['POST'])
def get_books_by_name_and_category():
    data = request.json
    bookname = data['bookname']
    category = data['category']
    books = Book.query.filter_by(bookname=bookname, category=category).all()
    book_list = []
    if not books:
        return Result.error(404, 'book not found'), 404
    else:
        for book in books:
            book_list.append(book.to_dict())
            return Result.success(book_list)


@api.route('/borrow', methods=['POST'])
def borrow_book():
    bookid = request.json.get('bookid')
    loandays = request.json.get('loandays')
    userid = request.json.get('userid')
    book = Book.query.get(bookid)

    if book is None:
        return Result.error(404, 'book not found')
    else:
        if book.borrowBook():
            Record(book.bookid, datetime.now(), loandays, userid).addRecord()
            return Result.success(None, "borrowed successfully")
        else:
            return Result.error(404, 'borrow failed')


@api.route('/return', methods=['POST'])
def return_book():
    recordid = request.json.get('recordid')
    record = Record.query.filter_by(recordid=recordid).first()

    if record is None:
        return Result.error(404, 'record not found')
    else:
        book = Book.query.filter_by(bookid=record.bookid).first()
        book.returnBook()
        record.deleteRecord()
        return Result.success(None, "returned successfully")


# 返回指定图书的图书封面
@api.route('/returnBookCover/<bookname>', methods=['GET'])
def return_book_cover(bookname):
    book = Book.query.filter_by(bookname=bookname).first()
    if book is None:
        return Result.error(404, 'book not found')
    else:
        img_url = '../' + book.coverpath
        print(img_url)
        return send_file(img_url, mimetype='image/jpg')


# 获取GPT的推荐
@api.route('/returnGPTRecommend', methods=['POST'])
def return_GPTRecommend():
    data = request.json
    content = data['content']
    return Result.success(GPT.main(content))


# 图书丢失损坏罚款功能:用户反馈图书损失时返回损失图书的价格
# 接受值：bookid userid
# 返回值: bookid 对应的 price
@api.route('/punish', methods=['POST'])
def punish_book():
    bookid = request.form.get('bookid')
    userid = request.form.get('userid')
    record = Record.query.filter_by(bookid=bookid, userid=userid).first()
    book = Book.query.filter_by(bookid=bookid).first()
    print(record)
    print(book)
    if book is None:
        return Result.error(404, 'book not found')
    else:
        if record is None:
            return Result.error(404, "record not found")
        else:
            fine = book.price
            return Result.success(fine)


# 图书丢失损坏罚款功能:用户缴纳完毕罚款后，删除借书记录,图书余量不再增加;
# 用户恢复某些权限(这部分功能待增加)
# 接受值：ispay(表示是否缴纳罚金:0--未缴纳，1--已缴纳) recordid
@api.route('/delete_record', methods=['POST'])
def delete_record():
    ispay = request.form.get('ispay')
    print(ispay)
    recordid = request.form.get('recordid')
    if ispay == '1':
        record = Record.query.filter_by(recordid=recordid).first()
        record.deleteRecord()
        return Result.success(None, 'fine has been paid')
    else:
        return Result.error(404, 'fine was not paid')


# 生成二维码
@api.route('/generate_qrcode/<bookid>', methods=['GET'])
def generate_qrcode(bookid):
    # 书籍信息
    book = Book.query.filter_by(bookid=bookid).first()
    if book is None:
        return Result.error(404, 'book not found')
    book_info = book.to_dict()
    # 创建一个QRCode实例
    qr = QRCode(
        version=1,
        error_correction=ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )

    # 添加数据
    qr.add_data(book_info)
    qr.make(fit=True)

    # 将二维码转换为PIL Image对象
    img = qr.make_image(fill_color="black", back_color="white")

    # 使用BytesIO来将PIL Image对象保存为字节流
    buffered = BytesIO()
    img.save(buffered, format="PNG")

    # 将字节流转换为Base64编码的字符串
    img_b64 = base64.b64encode(buffered.getvalue()).decode()

    # 返回一个JSON响应，包含Base64编码的二维码字符串
    return Result.success('data:image/png;base64,' + img_b64)
